<template>
  <div class="image-compressor" tabindex="0" @paste="handlePaste">
    <el-row :gutter="20">
      <el-col :span="12">
        <el-card class="input-card">
          <template #header>
            <div class="card-header">
              <span>原始图片</span>
              <div class="controls">
                <el-select v-model="format" placeholder="输出格式">
                  <el-option label="JPEG" value="jpeg" />
                  <el-option label="PNG" value="png" />
                </el-select>
                <div class="quality-control">
                  <span>质量: {{ quality }}%</span>
                  <el-slider
                    v-model="quality"
                    :min="1"
                    :max="100"
                    :step="1"
                    @change="handleQualityChange"
                    style="width: 200px; margin: 0 20px;"
                  />
                </div>
              </div>
            </div>
          </template>
          <div
            class="upload-area"
            @drop.prevent="handleDrop"
            @dragover.prevent
            @click="triggerUpload"
          >
            <input
              type="file"
              ref="fileInput"
              style="display: none"
              accept="image/*"
              @change="handleFileChange"
            />
            <div v-if="!inputImage" class="upload-placeholder">
              <el-icon><Upload /></el-icon>
              <div>点击或拖拽图片到此处</div>
            </div>
            <template v-else>
              <img :src="inputImage" class="preview-image" />
              <div class="file-info">
                原始大小: {{ formatFileSize(originalSize) }}
              </div>
            </template>
          </div>
        </el-card>
      </el-col>
      <el-col :span="12">
        <el-card class="output-card">
          <template #header>
            <div class="card-header">
              <span>压缩结果</span>
              <el-button type="primary" @click="downloadImage" :disabled="!outputImage">
                下载图片
              </el-button>
            </div>
          </template>
          <div class="result-area">
            <template v-if="outputImage">
              <img :src="outputImage" class="preview-image" />
              <div class="file-info">
                压缩后大小: {{ formatFileSize(compressedSize) }}
                <span class="compression-ratio" v-if="compressionRatio">
                  (压缩率: {{ compressionRatio }}%)
                </span>
              </div>
            </template>
            <div v-else class="placeholder">
              压缩后的图片将显示在这里
            </div>
          </div>
        </el-card>
      </el-col>
    </el-row>
  </div>
</template>

<script setup>
import { ref, watch, computed } from 'vue'
import { ElMessage } from 'element-plus'
import { Upload } from '@element-plus/icons-vue'

const fileInput = ref(null)
const inputImage = ref('')
const outputImage = ref('')
const quality = ref(80)
const format = ref('jpeg')
const originalSize = ref(0)
const compressedSize = ref(0)
const currentFile = ref(null)

// 添加防抖函数
const debounce = (fn, delay) => {
  let timer = null
  return function (...args) {
    if (timer) clearTimeout(timer)
    timer = setTimeout(() => {
      fn.apply(this, args)
    }, delay)
  }
}

// 修改监听器，添加防抖
watch(
  [quality, format],
  debounce(() => {
    if (currentFile.value) {
      processImage(currentFile.value, false) // 添加静默模式参数
    }
  }, 500) // 500ms 的防抖延迟
)

const triggerUpload = () => {
  fileInput.value.click()
}

const handleFileChange = (event) => {
  const file = event.target.files[0]
  if (file) {
    currentFile.value = file
    processImage(file)
  }
}

const handleDrop = (event) => {
  const file = event.dataTransfer.files[0]
  if (file && file.type.startsWith('image/')) {
    currentFile.value = file
    processImage(file)
  } else {
    ElMessage.error('请上传图片文件')
  }
}

// 修改 processImage 函数，添加静默模式参数
const processImage = (file, showMessage = true) => {
  originalSize.value = file.size
  const reader = new FileReader()
  reader.onload = (e) => {
    inputImage.value = e.target.result
    compressImage(e.target.result, showMessage)
  }
  reader.readAsDataURL(file)
}

// 修改 compressImage 函数，添加静默模式参数
const compressImage = async (dataUrl, showMessage = true) => {
  try {
    const response = await fetch(dataUrl)
    const blob = await response.blob()
    const file = new File([blob], 'image.jpg', { type: blob.type })

    const formData = new FormData()
    formData.append('image', file)
    formData.append('quality', quality.value)
    formData.append('format', format.value)

    const res = await fetch('http://localhost:5000/api/compress', {
      method: 'POST',
      body: formData
    })

    if (!res.ok) {
      throw new Error('压缩失败')
    }

    const compressedBlob = await res.blob()
    compressedSize.value = compressedBlob.size
    
    // 如果存在之前的URL，先释放它
    if (outputImage.value) {
      URL.revokeObjectURL(outputImage.value)
    }
    
    outputImage.value = URL.createObjectURL(compressedBlob)
    
    // 只在非静默模式下显示消息
    if (showMessage) {
      ElMessage.success('压缩成功')
    }
  } catch (error) {
    console.error('压缩失败:', error)
    // 只在非静默模式下显示错误消息
    if (showMessage) {
      ElMessage.error('压缩失败: ' + error.message)
    }
  }
}

const formatFileSize = (bytes) => {
  if (!bytes) return '0 B'
  const k = 1024
  const sizes = ['B', 'KB', 'MB', 'GB']
  const i = Math.floor(Math.log(bytes) / Math.log(k))
  return `${(bytes / Math.pow(k, i)).toFixed(2)} ${sizes[i]}`
}

const compressionRatio = computed(() => {
  if (!originalSize.value || !compressedSize.value) return 0
  return ((1 - compressedSize.value / originalSize.value) * 100).toFixed(1)
})

const downloadImage = () => {
  if (!outputImage.value) return
  const link = document.createElement('a')
  link.href = outputImage.value
  link.download = `compressed.${format.value}`
  link.click()
  URL.revokeObjectURL(outputImage.value)
}

// 处理粘贴事件
const handlePaste = (event) => {
  const items = event.clipboardData?.items
  if (!items) return

  // 查找剪贴板中的图片数据
  const imageItem = Array.from(items).find(
    item => item.type.indexOf('image') !== -1
  )

  if (imageItem) {
    // 获取图片文件
    const file = imageItem.getAsFile()
    if (file) {
      currentFile.value = file
      processImage(file)
      event.preventDefault() // 阻止默认粘贴行为
    }
  }
}
</script>

<style scoped>
.image-compressor {
  padding: 20px;
  outline: none; /* 移除 tabindex 带来的焦点边框 */
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.controls {
  display: flex;
  align-items: center;
  gap: 10px;
}

.upload-area {
  height: 400px;
  border: 2px dashed var(--el-border-color);
  border-radius: 4px;
  cursor: pointer;
  display: flex;
  justify-content: center;
  align-items: center;
  transition: border-color 0.3s;
}

.upload-area:hover {
  border-color: var(--el-color-primary);
}

.upload-placeholder {
  text-align: center;
  color: var(--el-text-color-secondary);
}

.upload-placeholder .el-icon {
  font-size: 48px;
  margin-bottom: 10px;
}

.preview-image {
  max-width: 100%;
  max-height: 400px;
  object-fit: contain;
}

.result-area {
  height: 400px;
  display: flex;
  justify-content: center;
  align-items: center;
}

.placeholder {
  color: var(--el-text-color-secondary);
}

.quality-control {
  display: flex;
  align-items: center;
  margin-left: 20px;
}

.file-info {
  position: absolute;
  bottom: 10px;
  left: 0;
  right: 0;
  text-align: center;
  padding: 5px;
  background-color: rgba(0, 0, 0, 0.6);
  color: white;
  font-size: 14px;
}

.compression-ratio {
  margin-left: 10px;
  color: var(--el-color-success);
}

.upload-area, .result-area {
  position: relative;
}
</style> 